package com.ship.dispatch.service.fob.impl;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ship.common.core.base.PageBean;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.common.business.service.BaseService;
import com.ship.common.core.utils.DateUtil;
import com.ship.common.security.utils.SecurityUtils;
import com.ship.dispatch.bean.ConShipping;
import com.ship.dispatch.bean.SpDispatchSchemeDetail;
import com.ship.dispatch.bean.SpDispatchSchemeExecute;
import com.ship.dispatch.bean.SpFobSublease;
import com.ship.dispatch.bean.fob.*;
import com.ship.dispatch.bpm.service.TaskService;
import com.ship.dispatch.bpm.utils.CalculateDateUtil;
import com.ship.dispatch.bpm.utils.JsonUtils;
import com.ship.dispatch.bpm.utils.TemplateParamUtils;
import com.ship.dispatch.bpm.vo.BpmTaskVo;
import com.ship.dispatch.bpm.vo.ManageEntityVo;
import com.ship.dispatch.bpm.vo.RebackTaskVo;
import com.ship.dispatch.bpm.vo.dto.FieldOptions;
import com.ship.dispatch.bpm.vo.dto.NodeConfigDto;
import com.ship.dispatch.bpm.vo.dto.RuntimeTaskDto;
import com.ship.dispatch.bpm.vo.dto.TaskDto;
import com.ship.dispatch.service.ConShippingService;
import com.ship.dispatch.service.SpDispatchSchemeDetailService;
import com.ship.dispatch.service.SpDispatchSchemeExecuteService;
import com.ship.dispatch.service.SpFobSubleaseService;
import com.ship.dispatch.service.fob.*;
//import com.sun.org.apache.xpath.internal.operations.Bool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;

/**
 *@title FobServiceImpl
 *@description
 *@author yl
 *@create 2023/12/14 0014
 */

@Service
public class FobServiceImpl implements FobService {

    @Value("${special.workingDays}")
    private String workingDays;
    @Value("${special.freeDays}")
    private String freeDays;

    private final Map taskNode;
    @Autowired
    RecordService recordService;
    @Autowired
    private TaskService taskService;
    @Autowired
    SpFobZzcbdlService spFobZzcbdlService;
    @Autowired
    SpFobXzcbdlService spFobXzcbdlService;
    @Autowired
    SpFobZddsfjlService spFobZddsfjlService;

    @Autowired
    SpFobZdxzdsfjlService spFobZdxzdsfjlService;

    @Autowired
    SpDispatchSchemeExecuteService spDispatchSchemeExecuteService;

    @Autowired
    SpFobTemplateService spFobTemplateService;
    @Autowired
    SpFobLabelItemService spFobLabelItemService;

    @Autowired
    SpFobSubleaseService spFobSubleaseService;

    @Autowired
    public FobServiceImpl() {
        this.taskNode = readJsonFile();
    }

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public RuntimeTaskDto getAssigenersAndSetEndDate(String processInstanceId,String taskId,String bussenKey, String type,String expectedLoadingDate,String taskName,String userId) {
        Object object = taskNode.get(type);
        RuntimeTaskDto dto = new RuntimeTaskDto();
        if(object!=null){
            NodeConfigDto nodeConfigDto = JsonUtils.jsonToObject(object.toString(), NodeConfigDto.class);
            Class baseClass = null;
            try {
                baseClass = Class.forName(nodeConfigDto.getServiceClassPath());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                return dto;
            }
            FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
            SpFobBaseBean spFobBaseBean = service.getBaseBeanByInstanceId(processInstanceId);
            // 没有配置超时时长则不计算超时
            Date da = null;
            if(expectedLoadingDate !=null && (nodeConfigDto.getExpectedLoadingFreeDateLength()!=null || nodeConfigDto.getExpectedLoadingWorkDateLength()!=null)){
                LocalDate endDate = CalculateDateUtil.calculateDate(expectedLoadingDate,
                        nodeConfigDto.getExpectedLoadingWorkDateLength(),
                        nodeConfigDto.getExpectedLoadingFreeDateLength(),workingDays,freeDays);
                ZoneId zone = ZoneId.systemDefault();
                Instant instant = endDate.atStartOfDay().atZone(zone).toInstant();
                da = Date.from(instant);
                dto.setExpectedLoadingDate(da);
            }
            if(spFobBaseBean!=null){
                spFobBaseBean.setTaskId(taskId);
                spFobBaseBean.setPlanEndDate(da);
                if(spFobBaseBean.getAddAssigeners()==null){
                    spFobBaseBean.setAddAssigeners(userId);
                    //spFobBaseBean.setAddAssigeners(userId+","+spFobBaseBean.getAddAssigeners());
                }
                dto.setAddAssigeners(spFobBaseBean.getAddAssigeners());
                spFobBaseBean.setStatus(0);
                service.updateEntityById(spFobBaseBean);
            }else {
                spFobBaseBean = new SpFobBaseBean();
                spFobBaseBean.setTaskId(taskId);
                spFobBaseBean.setPlanEndDate(dto.getExpectedLoadingDate());
                spFobBaseBean.setSchemeDetailId(Long.parseLong(bussenKey));
                spFobBaseBean.setAddAssigeners(userId);
                spFobBaseBean.setProceeInstanceId(processInstanceId);
                spFobBaseBean.setStatus(0);
                service.saveEntity(spFobBaseBean);
            }
            // 记录任务开始
            /*String bacthId = UUID.randomUUID().toString().trim().replaceAll("-", "");
            Record changeRecord = new Record();
            changeRecord.setBacthId(bacthId);
            changeRecord.setSchemeDetailId(Long.parseLong(bussenKey));
            changeRecord.setNodeKey(type);
            changeRecord.setRemark("开始 " + taskName+ " 任务");
            //创建人信息
            changeRecord.setCreateDate(new Date());
            recordService.save(changeRecord);*/
        }
        return dto;
    }

    @Transactional
    @Override
    public JsonResult manage(ManageEntityVo manageEntityVo) {
        if(manageEntityVo.getTaskId()==null && manageEntityVo.getOperationType()==1){
            return JsonResult.failed("当前节点任务未启动，不可进行完成操作!");
        }
        ObjectNode json = manageEntityVo.getData();
        String json2 = JsonUtils.objectToJson(json);
        Class baseClass = getServiceClass(manageEntityVo.getKey());
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        SpFobBaseBean tempBean = service.getBaseBeanByInstanceId(manageEntityVo.getProcessInstanceId());
        if(tempBean!=null && tempBean.getStatus()!=0 && manageEntityVo.getOperationType()==1){
            return JsonResult.failed("当前节点任务不可进行完成操作!");
        }
        service.updateEntity(manageEntityVo,  json2);
        if(manageEntityVo.getOperationType()==1){ // 完成任务，提交审批任务
            BpmTaskVo taskVo = new BpmTaskVo();
            taskVo.setTaskId(manageEntityVo.getTaskId());
            taskVo.setComment("完成");
            JsonResult result = taskService.complete(taskVo);
            //判断下游节点是否为开启状态
            List<TaskDto> startTasks = taskService.findTaskIdStartNode(manageEntityVo.getProcessInstanceId(),manageEntityVo.getTaskId());
            for (TaskDto dto : startTasks){
                baseClass = getServiceClass(dto.getKey());
                service = (FobBaseService) applicationContext.getBean(baseClass);
                SpFobBaseBean spFobBaseBean = service.getBaseBeanByInstanceId(manageEntityVo.getProcessInstanceId());
                if(spFobBaseBean!=null) {// 变更为未开始状态
                    spFobBaseBean.setStatus(0);
                    // 恢复任务为进行中状态
                    service.updateEntityById(spFobBaseBean);
                }
            }
            return result;
        }
        return JsonResult.success();
    }

    @Override
    public JsonResult getServiceFormData(String key, String id,Long serviceId) {
        Class baseClass = getServiceClass(key);
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        Object object = service.getFormData(id,serviceId);
        if(object==null){
            SpFobBaseBean spFobBaseBean = new SpFobBaseBean();
            SpDispatchSchemeExecute execute = spDispatchSchemeExecuteService.getExceuteByInstanceId(id);
            if(execute!=null){
                spFobBaseBean.setAddAssigeners(execute.getAssigeners());
            }else{
                SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(id);
                if(spFobSublease!=null){
                    spFobBaseBean.setAddAssigeners(spFobSublease.getAssigeners());
                }
            }
            spFobBaseBean.setStatus(-1);
            return JsonResult.success(spFobBaseBean);
        }
        Map<String,String> map = JsonUtils.jsonToMap(JsonUtils.objectToJson(object),String.class);
        if(map.get("status") == null){
            map.put("status","-1");
        }
        return JsonResult.success(map);
    }

    @Override
    public String getFileTypeByNodeKey(String key) {
        Object object = taskNode.get(key);
        if(object!=null){
            NodeConfigDto nodeConfigDto = JsonUtils.jsonToObject(object.toString(), NodeConfigDto.class);
            return nodeConfigDto.getFileType();
        }
        return "";
    }
    @Override
    public String getPlanDateByNodeKey(String key) {
        Object object = taskNode.get(key);
        if(object!=null){
            NodeConfigDto nodeConfigDto = JsonUtils.jsonToObject(object.toString(), NodeConfigDto.class);
            if(nodeConfigDto.getPlanDate()!=null){
                return nodeConfigDto.getPlanDate();
            }
            // 默认预计装载时间
            return "expectedLoadingDate";
        }
        return "";
    }

    @Autowired
    SpFobSalesZddsfjlService spFobSalesZddsfjlService;

    @Autowired
    SpFobReturnSalesZddsfjlService spFobReturnSalesZddsfjlService;


    @Autowired
    ConShippingService conShippingService;
    @Override
    public JsonResult getFobBaseInfo(String processInstanceId) {
        //List<FieldOptions> mm = spFobTemplateService.getCronInfo("ConShippingAgency",null);
        SpDispatchSchemeExecute spDispatchSchemeDetail = spDispatchSchemeExecuteService.getExceuteByInstanceId(processInstanceId);
        List<ObjectNode> list = new ArrayList<>();
        if(spDispatchSchemeDetail !=null){
            // 获取资源采购合同封装信息
            ObjectNode node = getContractCronInfo(spDispatchSchemeDetail);
            list.add(node);
            // 获取 资源销售合同信息
            ObjectNode node2 = getSellerContractCronInfo(spDispatchSchemeDetail);
            if(node2!=null){
                list.add(node2);
            }
            //船运合同信息
            ObjectNode node3 = getShipContractCronInfo(spDispatchSchemeDetail);
            if(node3!=null){
                list.add(node3);
            }
            List<SpFobZddsfjl> his = spFobZddsfjlService.list(new LambdaQueryWrapper<SpFobZddsfjl>().eq(SpFobZddsfjl::getProceeInstanceId,processInstanceId).ne(SpFobZddsfjl::getStatus,-2));
            //获取计量合同信息 SpFobZddsfjl
            if(his.size()>0) {
                SpFobZddsfjl spFobZddsfjl = his.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    ObjectNode node4 = getJlContractCronInfo(spFobZddsfjl.getCronId());
                    if(node4!=null){
                        list.add(node4);
                    }
                }
            }
            // 002
            List<SpFobSalesZddsfjl> seles = spFobSalesZddsfjlService.list(new LambdaQueryWrapper<SpFobSalesZddsfjl>().eq(SpFobSalesZddsfjl::getProceeInstanceId,processInstanceId).ne(SpFobSalesZddsfjl::getStatus,-2));
            if(seles.size()>0) {
                SpFobSalesZddsfjl spFobZddsfjl = seles.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    ObjectNode node4 = getJlContractCronInfo(spFobZddsfjl.getCronId());
                    if(node4!=null){
                        list.add(node4);
                    }
                }
            }
            // 003
            List<SpFobReturnSalesZddsfjl> returnSeles = spFobReturnSalesZddsfjlService.list(new LambdaQueryWrapper<SpFobReturnSalesZddsfjl>().eq(SpFobReturnSalesZddsfjl::getProceeInstanceId,processInstanceId).ne(SpFobReturnSalesZddsfjl::getStatus,-2));
            if(returnSeles.size()>0) {
                SpFobReturnSalesZddsfjl spFobZddsfjl = returnSeles.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    ObjectNode node4 = getJlContractCronInfo(spFobZddsfjl.getCronId());
                    if(node4!=null){
                        list.add(node4);
                    }
                }
            }
            List<SpFobZdxzdsfjl> his3 = spFobZdxzdsfjlService.list(new LambdaQueryWrapper<SpFobZdxzdsfjl>().eq(SpFobZdxzdsfjl::getProceeInstanceId,processInstanceId));
            //获取计量合同信息 SpFobZddsfjl
            if(his3.size()>0) {
                SpFobZdxzdsfjl spFobZdxzdsfjl = his3.get(0);
                if (spFobZdxzdsfjl.getCronId() != null) {
                    ObjectNode node4 = getJlContractCronInfo(spFobZdxzdsfjl.getCronId());
                    if(node4!=null){
                        list.add(node4);
                    }
                }
            }
            // 获取装载船舶代理
            List<SpFobZzcbdl> his2 = spFobZzcbdlService.list(new LambdaQueryWrapper<SpFobZzcbdl>().eq(SpFobZzcbdl::getProceeInstanceId,processInstanceId));
            if(his2.size()>0) {
                SpFobZzcbdl spFobZddsfjl = his2.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    ObjectNode node4 = getCBContractCronInfo(spFobZddsfjl.getCronId());
                    if(node4!=null){
                        list.add(node4);
                    }
                }
            }

            List<SpFobXzcbdl> his4 = spFobXzcbdlService.list(new LambdaQueryWrapper<SpFobXzcbdl>().eq(SpFobXzcbdl::getProceeInstanceId,processInstanceId));
            if(his4.size()>0) {
                SpFobXzcbdl spFobZddsfjl = his4.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    ObjectNode node4 = getCBContractCronInfo(spFobZddsfjl.getCronId());
                    if(node4!=null){
                        list.add(node4);
                    }
                }
            }
        }
        else{
            SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(processInstanceId);
            if(spFobSublease!=null){
                ConShipping conShipping = conShippingService.getById(spFobSublease.getConId());
                if(conShipping!=null){
                    ObjectMapper objectMapper = new ObjectMapper();
                    ObjectNode node = objectMapper.createObjectNode();
                    node.put("title",conShipping.getContractName());
                    node.put("id",conShipping.getId());
                    node.put("type","1");
                    node.put("url","");
                    ArrayNode items = objectMapper.createArrayNode();
                    ObjectNode item = objectMapper.createObjectNode();
                    item.put("label","船舶名称");
                    item.put("value",conShipping.getShipName());
                    items.add(item);
                    item = objectMapper.createObjectNode();
                    item.put("label","IMO");
                    item.put("value",conShipping.getImo());
                    items.add(item);
                    item = objectMapper.createObjectNode();
                    item.put("label","合同类型");
                    if(conShipping.getContractType()==1){
                        item.put("value","租入长期船");
                    }else if(conShipping.getContractType()==2){
                        item.put("value","租入短期船");
                    }else if(conShipping.getContractType()==3){
                        item.put("value","船舶租出");
                    }else if(conShipping.getContractType()==4){
                        item.put("value","内部转租");
                    }else {
                        item.put("value",conShipping.getContractType());
                    }
                    //item.put("value",conShipping.getContractType());
                    items.add(item);

                    item = objectMapper.createObjectNode();
                    item.put("label","合同主体");
                    if("1".equals(conShipping.getTradeBody())){
                        item.put("value","国贸");
                    }else{
                        item.put("value","新贸");
                    }
                    item = objectMapper.createObjectNode();
                    item.put("label","签订日期");
                    if(conShipping.getSigningDate()!=null){
                        item.put("value",DateUtil.date2Str(conShipping.getSigningDate(),"yyyy-MM-dd"));
                    }else{
                        item.put("value","");
                    }

                    items.add(item);
                    node.put("item",items);
                    list.add(node);

                }
            }
        }
        return JsonResult.success(list);
    }

    @Override
    public JsonResult getFileTemplateInfo(ManageEntityVo manageEntityVo) {
        return null;
    }

    @Override
    public SpFobBaseBean getAssigenersByNode(String processInstaneId, String nodeType) {
        try{
            Class baseClass = getServiceClass(nodeType);
            FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
            SpFobBaseBean spFobBaseBean = service.getBaseBeanByInstanceId(processInstaneId);
            if(spFobBaseBean==null){
                return null;
            }
            return spFobBaseBean;
        }catch (Exception e){
            e.printStackTrace();
        }
       return null;
    }

    @Override
    public List<SpFobFileRecord> getBaseCronInfo(String processInstanceId) {
        SpDispatchSchemeExecute spDispatchSchemeDetail = spDispatchSchemeExecuteService.getExceuteByInstanceId(processInstanceId);
        List<SpFobFileRecord> list = new ArrayList<>();
        if(spDispatchSchemeDetail !=null){
            // 获取资源采购合同封装信息
            SpFobFileRecord record = new SpFobFileRecord();
            record.setId(spDispatchSchemeDetail.getResourceContract());
            record.setName(spDispatchSchemeDetail.getContractName());
            record.setFileType("合同类");
            record.setConType(1);
            record.setIsCron(1);
            list.add(record);
            // 获取 资源销售合同信息
            if(spDispatchSchemeDetail.getSellerResourceContract()!=null){
                SpFobFileRecord record1 = new SpFobFileRecord();
                record1.setId(spDispatchSchemeDetail.getSellerResourceContract());
                record1.setName(spDispatchSchemeDetail.getSellerContractName());
                record1.setFileType("合同类");
                record1.setConType(1);
                record1.setIsCron(1);
                list.add(record1);
            }
            //船运合同信息
            if(spDispatchSchemeDetail.getShipContractId()!=null){
                SpFobFileRecord record2 = new SpFobFileRecord();
                record2.setId(spDispatchSchemeDetail.getShipContractId());
                record2.setName(spDispatchSchemeDetail.getShipContractName());
                record2.setFileType("合同类");
                record2.setConType(2);
                record2.setIsCron(1);
                list.add(record2);
            }
            List<SpFobZddsfjl> his = spFobZddsfjlService.list(new LambdaQueryWrapper<SpFobZddsfjl>().eq(SpFobZddsfjl::getProceeInstanceId,processInstanceId));
            //获取计量合同信息 SpFobZddsfjl
            if(his.size()>0) {
                SpFobZddsfjl spFobZddsfjl = his.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    Map<String, String> map = spFobZddsfjlService.findConThirdPartyMeasurement(spFobZddsfjl.getCronId());
                    if (map != null) {
                        SpFobFileRecord record3 = new SpFobFileRecord();
                        record3.setId(Long.parseLong(spFobZddsfjl.getCronId()));
                        record3.setName(map.get("contract_name"));
                        record3.setFileType("合同类");
                        record3.setConType(4);
                        record3.setIsCron(1);
                        list.add(record3);
                    }
                }
            }
            List<SpFobZdxzdsfjl> his3 = spFobZdxzdsfjlService.list(new LambdaQueryWrapper<SpFobZdxzdsfjl>().eq(SpFobZdxzdsfjl::getProceeInstanceId,processInstanceId));
            //获取计量合同信息 SpFobZddsfjl
            if(his3.size()>0) {
                SpFobZdxzdsfjl spFobZdxzdsfjl = his3.get(0);
                if (spFobZdxzdsfjl.getCronId() != null) {
                    Map<String,String> map = spFobZddsfjlService.findConThirdPartyMeasurement(spFobZdxzdsfjl.getCronId());
                    if(map!=null){
                        SpFobFileRecord record4 = new SpFobFileRecord();
                        record4.setId(Long.parseLong(spFobZdxzdsfjl.getCronId()));
                        record4.setName(map.get("contract_name"));
                        record4.setFileType("合同类");
                        record4.setConType(4);
                        record4.setIsCron(1);
                        list.add(record4);
                    }
                }
            }
            // 获取装载船舶代理
            List<SpFobZzcbdl> his2 = spFobZzcbdlService.list(new LambdaQueryWrapper<SpFobZzcbdl>().eq(SpFobZzcbdl::getProceeInstanceId,processInstanceId));
            if(his2.size()>0) {
                SpFobZzcbdl spFobZddsfjl = his2.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    Map<String,Object> map = spFobZzcbdlService.findConShippingAgency(spFobZddsfjl.getCronId());
                    if(map!=null) {
                        SpFobFileRecord record5 = new SpFobFileRecord();
                        record5.setId(Long.parseLong(spFobZddsfjl.getCronId()));
                        record5.setName(map.get("contract_name")+"");
                        record5.setFileType("合同类");
                        record5.setConType(3);
                        record5.setIsCron(1);
                        list.add(record5);
                    }
                }
            }

            List<SpFobXzcbdl> his4 = spFobXzcbdlService.list(new LambdaQueryWrapper<SpFobXzcbdl>().eq(SpFobXzcbdl::getProceeInstanceId,processInstanceId));
            if(his4.size()>0) {
                SpFobXzcbdl spFobZddsfjl = his4.get(0);
                if (spFobZddsfjl.getCronId() != null) {
                    Map<String,Object> map = spFobZzcbdlService.findConShippingAgency(spFobZddsfjl.getCronId());
                    if(map!=null) {
                        SpFobFileRecord record6 = new SpFobFileRecord();
                        record6.setId(Long.parseLong(spFobZddsfjl.getCronId()));
                        record6.setName(map.get("contract_name")+"");
                        record6.setFileType("合同类");
                        record6.setConType(3);
                        record6.setIsCron(1);
                        list.add(record6);
                    }
                }
            }
        }
        return list;
    }

    @Transactional
    @Override
    public JsonResult rebackTask(RebackTaskVo rebackTaskVo) {
        Class baseClass = getServiceClass(rebackTaskVo.getKey());
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        SpFobBaseBean spFobBaseBean = service.getBaseBeanByInstanceId(rebackTaskVo.getProcessInstanceId());
        if(spFobBaseBean!=null){// 变更为执行中状态
            if(spFobBaseBean.getStatus()!=1){
                return JsonResult.failed("只能撤换已经完成的任务");
            }
            spFobBaseBean.setStatus(0);
            service.updateEntityById(spFobBaseBean);
            // 撤回后续任务
            // 获取待撤回任务
            List<TaskDto> rebackTasks = taskService.findTaskIdNextNode(spFobBaseBean.getProceeInstanceId(),spFobBaseBean.getTaskId());
            for (TaskDto dto : rebackTasks){
                baseClass = getServiceClass(dto.getKey());
                service = (FobBaseService) applicationContext.getBean(baseClass);
                spFobBaseBean = service.getBaseBeanByInstanceId(rebackTaskVo.getProcessInstanceId());
                if(spFobBaseBean!=null) {// 变更为未开始状态
                   /* if (spFobBaseBean.getStatus() != 1) {
                        return JsonResult.failed("只能撤换已经完成的任务");
                    }*/
                    spFobBaseBean.setStatus(-1);
                    // 撤回后续任务
                    service.updateEntityById(spFobBaseBean);
                }
            }
            SpDispatchSchemeExecute execute = spDispatchSchemeExecuteService.getExceuteByInstanceId(rebackTaskVo.getProcessInstanceId());
            if(execute!=null && execute.getStatus()==1){
                execute.setStatus(0);
                spDispatchSchemeExecuteService.updateById(execute);
            }else {
                SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(rebackTaskVo.getProcessInstanceId());
                if(spFobSublease!=null && spFobSublease.getStatus()==1){
                    spFobSublease.setStatus(0);
                    spFobSubleaseService.updateById(spFobSublease);
                }
            }
            String taskName = taskService.getTaskName(rebackTaskVo.getTaskId());
            // 记录 撤换任务记录
            String bacthId = UUID.randomUUID().toString().trim().replaceAll("-", "");
            Record changeRecord = new Record();
            changeRecord.setBacthId(bacthId);
            changeRecord.setSchemeDetailId(rebackTaskVo.getSchemeDetailId());
            changeRecord.setNodeKey(rebackTaskVo.getKey());
            //创建人信息
            changeRecord.setCreateDate(new Date());
            changeRecord.setProceeInstanceId(rebackTaskVo.getProcessInstanceId());
            changeRecord.setCreateBy(SecurityUtils.getUsername());
            changeRecord.setType(1+"");
            changeRecord.setRemark(SecurityUtils.getUsername() +"撤回" + taskName +"任务");
            recordService.save(changeRecord);
        }
        return JsonResult.success();
    }

    @Override
    public JsonResult getEmailTemplateInfo(Long templateId,String processInstanceId) {
        SpFobTemplate spFobTemplate = spFobTemplateService.getById(templateId);
        if(spFobTemplate==null){
            return JsonResult.success("");
        }
        List<String> labels = new ArrayList<>();
        labels = TemplateParamUtils.templateLabel(spFobTemplate.getContent(),labels);
        // 处理 获取数据逻辑
        if(labels.size()>0){
            String nodeKey = spFobTemplate.getTemplateKey();
            //nodeKey =nodeKey.substring(0,nodeKey.lastIndexOf("-"));
            Map<String,String> labelResult = spFobLabelItemService.getLabelKesData(nodeKey,labels,processInstanceId);
            String result = TemplateParamUtils.processDynamicLabelParams2(spFobTemplate.getContent(),labelResult);
            result = result.replaceAll("\\n","");
            return JsonResult.success(result);
        }
        return JsonResult.success(spFobTemplate.getContent());
    }

    @Transactional
    @Override
    public JsonResult completeTask(ManageEntityVo manageEntityVo) throws IOException {
        /*
        if(manageEntityVo.getOperationType()!=1){
            return JsonResult.failed("操作类型不对，请确认是否完成任务");
        }*/
        /*if(manageEntityVo.getTaskId()==null){
            return JsonResult.failed("当前节点任务未启动，不可进行操作!");
        }*/
        Class baseClass = getServiceClass(manageEntityVo.getKey());
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        SpFobBaseBean spFobBaseBean =  service.getBaseBeanByInstanceId(manageEntityVo.getProcessInstanceId());
        manageEntityVo.setSchemeDetailId(spFobBaseBean.getSchemeDetailId());
        if(manageEntityVo.getOperationType()==1) { // 完成任务，提交审批任务
            //校验当前是否开启审批 开启审批校验审批是否已经通过
            Boolean flag = service.checkApproveStatus(spFobBaseBean.getId());
            if(!flag || spFobBaseBean.getStatus()==1 || spFobBaseBean.getStatus()==-1){
                return JsonResult.failed("当前任务不可操作完成");
            }
            BpmTaskVo taskVo = new BpmTaskVo();
            taskVo.setTaskId(manageEntityVo.getTaskId());
            taskVo.setComment("完成");
            JsonResult result = taskService.complete(taskVo);
            spFobBaseBean.setStatus(1);
            spFobBaseBean.setRealEndDate(new Date());
            service.updateById(spFobBaseBean);
            //完成任务创建订单
            service.createPayOrder(spFobBaseBean.getId());
            service.createCostInfo(spFobBaseBean.getId(),manageEntityVo.getKey());
            try{

            }catch (Exception e){
                throw new BusException("同步订单错误", BaseResultCode.GENERAL_ERROR);
            }
            //判断下游节点是否为开启状态
            List<TaskDto> startTasks = taskService.findTaskIdStartNode(manageEntityVo.getProcessInstanceId(),manageEntityVo.getTaskId());
            for (TaskDto dto : startTasks){
                baseClass = getServiceClass(dto.getKey());
                service = (FobBaseService) applicationContext.getBean(baseClass);
                spFobBaseBean = service.getBaseBeanByInstanceId(manageEntityVo.getProcessInstanceId());
                if(spFobBaseBean!=null) {// 变更为未开始状态
                    spFobBaseBean.setStatus(0);
                    // 恢复任务为进行中状态
                    service.updateEntityById(spFobBaseBean);
                }
            }
            String bacthId = UUID.randomUUID().toString().trim().replaceAll("-", "");
            Record changeRecord = new Record();
            String taskName = taskService.getNodeNameByKey(manageEntityVo.getKey());
            changeRecord.setBacthId(bacthId);
            changeRecord.setSchemeDetailId(manageEntityVo.getSchemeDetailId());
            changeRecord.setNodeKey(manageEntityVo.getKey());
            //创建人信息
            changeRecord.setCreateDate(new Date());
            //TODO 获取登录人信息
            changeRecord.setProceeInstanceId(manageEntityVo.getProcessInstanceId());
            changeRecord.setCreateBy(SecurityUtils.getUsername());
            changeRecord.setType(1+"");
            changeRecord.setRemark(SecurityUtils.getUsername()+" 完成 "+taskName+" 任务");
            recordService.save(changeRecord);
            return result;
        }else if(manageEntityVo.getOperationType()==0){ // 撤回进行中
            if(spFobBaseBean.getStatus()!=1){
                return JsonResult.failed("当前任务不可撤回！");
            }
            RebackTaskVo rebackTaskVo = new RebackTaskVo();
            rebackTaskVo.setTaskId(manageEntityVo.getTaskId());
            rebackTaskVo.setProcessInstanceId(manageEntityVo.getProcessInstanceId());
            rebackTaskVo.setFormKey(manageEntityVo.getFormKey());
            rebackTaskVo.setKey(manageEntityVo.getKey());
            rebackTaskVo.setSchemeDetailId(manageEntityVo.getSchemeDetailId());
            rebackTaskVo.setOperationType(-2);
            return this.rebackTask(rebackTaskVo);
        }
        return JsonResult.success();
    }

    @Override
    public JsonResult addForm(RebackTaskVo addFromVo) {
        Class baseClass = getServiceClass(addFromVo.getKey());
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        SpFobBaseBean spFobBaseBean = service.getBaseBeanByInstanceId(addFromVo.getProcessInstanceId());
        if(spFobBaseBean==null){
            return JsonResult.failed("当前节点未执行信息，不需要任务执行");
        }
        if(spFobBaseBean.getStatus()!=0){
            return JsonResult.failed("只能对当前进行中的任务进行复制处理");
        }
        spFobBaseBean.setStatus(-2);
        service.updateById(spFobBaseBean);
        SpFobBaseBean baseBean = new SpFobBaseBean();
        baseBean.setAddAssigeners(spFobBaseBean.getAddAssigeners());
        baseBean.setProceeInstanceId(spFobBaseBean.getProceeInstanceId());
        baseBean.setPlanEndDate(spFobBaseBean.getPlanEndDate());
        baseBean.setTaskId(spFobBaseBean.getTaskId());
        baseBean.setSchemeDetailId(spFobBaseBean.getSchemeDetailId());
        baseBean.setStatus(0);
        service.saveEntity(baseBean);
        return JsonResult.success();
    }

    @Override
    public List<Long> findServieData(String key, String processInstaneId) {
        Class baseClass = getServiceClass(key);
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        return  service.findServieData(processInstaneId);
    }

    // 船舶代理
    private ObjectNode getCBContractCronInfo(String cronId) {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,Object> map = spFobZzcbdlService.findConShippingAgency(cronId);
        if(map!=null){
            ObjectNode node = objectMapper.createObjectNode();
            node.put("title",map.get("contract_name")+"");
            node.put("id",cronId);
            node.put("url","");
            node.put("type","3");
            ArrayNode items = objectMapper.createArrayNode();
            ObjectNode item = objectMapper.createObjectNode();
            item.put("label","公司名称");
            item.put("value",map.get("company_name")+"");
            items.add(item);
            item = objectMapper.createObjectNode();
            item.put("label","合同主体");
            if("1".equals(map.get("trade_body"))){
                item.put("value","国贸");
            }else{
                item.put("value","新贸");
            }
            //item.put("value",map.get("tradeBody"));
            items.add(item);
            node.put("item",items);
            return node;
        }
        return null;
    }


    private ObjectNode getJlContractCronInfo(String cronId) {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,String> map = spFobZddsfjlService.findConThirdPartyMeasurement(cronId);
        if(map!=null){
            ObjectNode node = objectMapper.createObjectNode();
            node.put("title",map.get("contract_name"));
            node.put("id",cronId);
            node.put("url","");
            node.put("type","4");
            ArrayNode items = objectMapper.createArrayNode();
            ObjectNode item = objectMapper.createObjectNode();
            item.put("label","公司名称");
            item.put("value",map.get("party_b"));
            items.add(item);
            item = objectMapper.createObjectNode();
            item.put("label","合同主体");
            if("1".equals(map.get("trade_body"))){
                item.put("value","国贸");
            }else{
                item.put("value","新贸");
            }

            items.add(item);
            node.put("item",items);
            return node;
        }
        return null;
    }

    /**
     * 封装资源采购合同信息
     * @param spDispatchSchemeDetail
     * @return
     */
    ObjectNode getContractCronInfo(SpDispatchSchemeExecute spDispatchSchemeDetail){
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode node = objectMapper.createObjectNode();
        node.put("title",spDispatchSchemeDetail.getContractName());
        node.put("id",spDispatchSchemeDetail.getResourceContract());
        node.put("type","1");
        node.put("url","");
        ArrayNode items = objectMapper.createArrayNode();
        ObjectNode item = objectMapper.createObjectNode();
        item.put("label","资源方(卖方)");
        item.put("value",spDispatchSchemeDetail.getSeller());
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","装载港");
        item.put("value",spDispatchSchemeDetail.getExpectedLoadingPort());
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","预计装载时间");
        //item.put("value",spDispatchSchemeDetail.getExpectedLoadingDate().toString());
        if(spDispatchSchemeDetail.getExpectedLoadingDate()!=null){
            item.put("value",DateUtil.date2Str(spDispatchSchemeDetail.getExpectedLoadingDate(),"yyyy-MM-dd"));
        }else {
            item.put("value","");
        }
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","实际装载时间");
        //item.put("value",spDispatchSchemeDetail.getRealityUnloadingDate()!=null?spDispatchSchemeDetail.getRealityUnloadingDate().toString():"");
        if(spDispatchSchemeDetail.getRealityLoadingDate()!=null){
            item.put("value",DateUtil.date2Str(spDispatchSchemeDetail.getRealityLoadingDate(),"yyyy-MM-dd"));
        }else {
            item.put("value","");
        }
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","贸易主体");
        if(spDispatchSchemeDetail.getTradeBody()==1){
            item.put("value","国贸");
        }else if(spDispatchSchemeDetail.getTradeBody()==2){
            item.put("value","新贸");
        }else {
            item.put("value","");
        }
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","贸易类型");
        if(spDispatchSchemeDetail.getTradeType()==1){
            item.put("value","长协");
        }else if(spDispatchSchemeDetail.getTradeType()==2){
            item.put("value","中期");
        }else if(spDispatchSchemeDetail.getTradeType()==3){
            item.put("value","现货");
        }else {
            item.put("value","");
        }

        items.add(item);
        node.put("item",items);
        return node;
    }

    /**
     * 封装资源销售合同信息
     * @param spDispatchSchemeDetail
     * @return
     */
    ObjectNode getSellerContractCronInfo(SpDispatchSchemeExecute spDispatchSchemeDetail){
        ObjectMapper objectMapper = new ObjectMapper();
        if(spDispatchSchemeDetail.getSellerResourceContract()==null) return null;
        ObjectNode node = objectMapper.createObjectNode();
        node.put("title",spDispatchSchemeDetail.getSellerContractName());
        node.put("id",spDispatchSchemeDetail.getSellerResourceContract());
        node.put("type","1");
        node.put("url","");
        ArrayNode items = objectMapper.createArrayNode();
        ObjectNode item = objectMapper.createObjectNode();
        item.put("label","买方");
        item.put("value",spDispatchSchemeDetail.getBuyer());
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","卸载港");
        item.put("value",spDispatchSchemeDetail.getExpectedUnloadingPort());
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","预计装载时间");
        if(spDispatchSchemeDetail.getExpectedLoadingDate()!=null){
            item.put("value",DateUtil.date2Str(spDispatchSchemeDetail.getExpectedLoadingDate(),"yyyy-MM-dd"));
        }else {
            item.put("value","");
        }
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","实际卸载时间");
        if(spDispatchSchemeDetail.getRealityUnloadingDate()!=null){
            item.put("value",DateUtil.date2Str(spDispatchSchemeDetail.getRealityUnloadingDate(),"yyyy-MM-dd"));
        }else {
            item.put("value","");
        }
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","贸易主体");
        if(spDispatchSchemeDetail.getSellerTradeBody()==1){
            item.put("value","国贸");
        }else if(spDispatchSchemeDetail.getSellerTradeBody()==2){
            item.put("value","新贸");
        }else {
            item.put("value",spDispatchSchemeDetail.getSellerTradeBody());
        }
        items.add(item);
        node.put("item",items);
        return node;
    }

    /**
     * 获取船运合同信息封装
     * @param spDispatchSchemeDetail
     * @return
     */
    ObjectNode getShipContractCronInfo(SpDispatchSchemeExecute spDispatchSchemeDetail){
        ObjectMapper objectMapper = new ObjectMapper();
        if(spDispatchSchemeDetail.getShipContractId()==null) return null;
        ObjectNode node = objectMapper.createObjectNode();
        node.put("title",spDispatchSchemeDetail.getShipContractName());
        node.put("id",spDispatchSchemeDetail.getShipContractId());
        node.put("type","2");
        node.put("url","");
        ArrayNode items = objectMapper.createArrayNode();
        ObjectNode item = objectMapper.createObjectNode();
        item.put("label","船舶名称");
        item.put("value",spDispatchSchemeDetail.getShipName());
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","IMO");
        item.put("value",spDispatchSchemeDetail.getImo());
        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","船运合同类型");
        if(spDispatchSchemeDetail.getShipContractType()==1){
            item.put("value","租入长期船");
        }else if(spDispatchSchemeDetail.getShipContractType()==2){
            item.put("value","租入短期船");
        }else if(spDispatchSchemeDetail.getShipContractType()==3){
            item.put("value","船舶租出");
        }else if(spDispatchSchemeDetail.getShipContractType()==4){
            item.put("value","内部转租");
        }else {
            item.put("value",spDispatchSchemeDetail.getShipContractType());
        }

        items.add(item);
        item = objectMapper.createObjectNode();
        item.put("label","贸易主体");
        if(spDispatchSchemeDetail.getShipTradeBody()==1){
            item.put("value","国贸");
        }else if(spDispatchSchemeDetail.getShipTradeBody()==2){
            item.put("value","新贸");
        }else{
            item.put("value",spDispatchSchemeDetail.getShipTradeBody());
        }
        //item.put("value",spDispatchSchemeDetail.getShipTradeBody()==1?"国贸":"新贸");
        items.add(item);
        node.put("item",items);
        return node;
    }

    @Override
    public JsonResult getTemplateInfo(ManageEntityVo manageEntityVo) {
        Class baseClass = getServiceClass(manageEntityVo.getKey());
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        return JsonResult.success(service.getTemplateParam(manageEntityVo));
    }

    public Class getServiceClass(String type) {
        Object object = taskNode.get(type);
        Class baseClass = null;
        if (object != null) {
            NodeConfigDto nodeConfigDto = JsonUtils.jsonToObject(object.toString(), NodeConfigDto.class);
            try {
                baseClass = Class.forName(nodeConfigDto.getServiceClassPath());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return baseClass;
    }

    @Override
    public void startApprovalProcess(Long serviceId, String key) {
        Class baseClass = getServiceClass(key);
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        service.startPostInstance(serviceId,key);
    }

    @Override
    public void updateApprovaResult(String businessKey, int status, String processDefinitionKey, String serviceType) {
        Class baseClass = getServiceClass(serviceType);
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        service.updateApprovaResult(Long.parseLong(businessKey),status);
    }

    @Override
    public SpFobBaseBean getSpFobBaseBean(String key, String processInstanceId) {
        Class baseClass = getServiceClass(key);
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
         SpFobBaseBean spFobBaseBean = service.getBaseBeanByInstanceId(processInstanceId);
        return spFobBaseBean;
    }

    @Override
    public String getExecuteInstance(String serviceType, Long serviceId) {
        Class baseClass = getServiceClass(serviceType);
        FobBaseService service = (FobBaseService) applicationContext.getBean(baseClass);
        SpFobBaseBean spFobBaseBean = (SpFobBaseBean) service.getById(serviceId);
        return spFobBaseBean!=null?spFobBaseBean.getProceeInstanceId():null;
    }

    public Map readJsonFile() {
        try{
            ClassPathResource resource = new ClassPathResource("service_node.json");
            InputStream inputStream = resource.getInputStream();
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode myObject = objectMapper.readValue(inputStream, JsonNode.class);
            Map mode = JSONUtil.toBean(myObject.toString(),Map.class);
            return mode;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}
